//===============================================================================
// Microsoft patterns & practices Enterprise Library Contribution
// Query Application Block
//===============================================================================

using System.Configuration;
using System.Data;
using EntLibContrib.Query.Queries;
using EntLibContrib.Query.Database.Properties;

namespace EntLibContrib.Query.Configuration
{
    using System;
    using System.Linq.Expressions;
    using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ContainerModel;
    using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.Design;
    using Microsoft.Practices.EnterpriseLibrary.Data;
    using Microsoft.Practices.EnterpriseLibrary.Data.Configuration;

    /// <summary>
	/// Configuration information for DataQueryData. This class represents the extra information, over and
	/// above what is defined in <see cref="QueryData" />, needed to connect resource to the Data block.
	/// </summary>
    [ResourceDescription(typeof(DesignResources), "DataQueryDataDescription")]
    [ResourceDisplayName(typeof(DesignResources), "DataQueryDataDisplayName")]
    [AddSateliteProviderCommand("connectionStrings", typeof(DatabaseSettings), "DefaultDatabase", "DatabaseInstanceName")]
    [System.ComponentModel.Browsable(true)]
    public class DataQueryData : QueryData
	{
		private const string databaseInstanceNameProperty = "databaseInstanceName";
		private const string commandProperty = "command";
		private const string commandTypeProperty = "commandType";

		/// <summary>
		/// Name of the database instance to use for the data source. The Instance must be defined in Data configuration.
		/// </summary>
        [ConfigurationProperty(databaseInstanceNameProperty, IsRequired = true)]
        [ResourceDescription(typeof(DesignResources), "DataQueryDataDatabaseInstanceNameDescription")]
        [ResourceDisplayName(typeof(DesignResources), "DataQueryDataDatabaseInstanceNameDisplayName")]
        [Reference(typeof(ConnectionStringSettingsCollection), typeof(ConnectionStringSettings))]
		public string DatabaseInstanceName
		{
			get { return (string)base[databaseInstanceNameProperty]; }
			set { base[databaseInstanceNameProperty] = value; }
		}

		/// <summary>
		/// Name of the data command to use. This can be a Stored Procedure name or a SQL query string.
		/// </summary>
		[ConfigurationProperty(commandProperty, IsRequired = true)]
        [ResourceDescription(typeof(DesignResources), "DataQueryDataCommandDescription")]
        [ResourceDisplayName(typeof(DesignResources), "DataQueryDataCommandDisplayName")]
		public string Command
		{
			get { return (string)base[commandProperty]; }
			set { base[commandProperty] = value; }
		}

		/// <summary>
		/// Type of data command to use. This can be a stored procedure or text.
		/// </summary>
		[ConfigurationProperty(commandTypeProperty, IsRequired = true, DefaultValue = CommandType.Text)]
        [ResourceDescription(typeof(DesignResources), "DataQueryDataCommandTypeDescription")]
        [ResourceDisplayName(typeof(DesignResources), "DataQueryDataCommandTypeDisplayName")]
		public CommandType CommandType
		{
			get { return (CommandType)base[commandTypeProperty]; }
			set { base[commandTypeProperty] = value; }
		}
		
        /// <summary>
		/// Initializes a new instance of the <see cref="DataQueryData"/> class.
		/// </summary>
		/// <overloads>
		/// Initializes an instance of a <see cref="DataQueryData"/> class.
		/// </overloads>
		public DataQueryData()
            : base(null, typeof(DataQuery))
		{
		}

		/// <summary>
		/// Initialize a new instance of the <see cref="DataQueryData"/> class.
		/// </summary>
		/// <param name="name">The name of the <see cref="DataQueryData"/>.</param>
		/// <param name="customCommandName">Name of the custom command.</param>
		/// <param name="parameterSetName">Name of the parameter set.</param>
		/// <param name="databaseInstanceName">Name of the database instance to use for the data source. Instance must be defined in Data configuration.</param>
		/// <param name="command">The command.</param>
		/// <param name="commandType">Type of the command.</param>
		public DataQueryData(string name, string customCommandName, string parameterSetName, string databaseInstanceName, string command, CommandType commandType)
			: base(name, typeof(DataQuery), customCommandName, parameterSetName)
		{
			this.DatabaseInstanceName = databaseInstanceName;
			this.Command = command;
			this.CommandType = commandType;
		}

        /// <summary>
        /// Returns the <see cref="TypeRegistration"/> entry for the current concrete type represented by this 
        /// configuration object.
        /// </summary>
        /// <returns>A registry entry.</returns>
        protected override Expression<Func<IQuery>> GetQueryCreationExpression()
        {
            return () =>
                new DataQuery(Name,
                    Container.Resolved<Database>(DatabaseInstanceName),
                    Command,
                    CommandType,
                    Container.ResolvedIfNotNull<ICommand>(CustomCommandName),
                    Container.ResolvedIfNotNull<IParameterSet>(ParameterSetName));
        }
	}
}